'Name:		    oeColor.vb														##
'Author:        schachmat														##
'Last modified: 21.8.2007														##
'Status:																		##
'	functionality:			80%													##
'	documentation intern:	05%													##
'	documentation extern:	00%													##
'Comments:																		##
'																				##
'																				##
'																				##
'																				##
'																				##
'#################################################################################


'The MIT License

'Copyright (c) 2007 Markus Teich

'Permission is hereby granted, free of charge, to any person obtaining a copy
'of this software and associated documentation files (the "Software"), to deal
'in the Software without restriction, including without limitation the rights
'to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
'copies of the Software, and to permit persons to whom the Software is
'furnished to do so, subject to the following conditions:

'The above copyright notice and this permission notice shall be included in
'all copies or substantial portions of the Software.

'THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
'IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
'FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
'AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
'LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
'OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
'THE SOFTWARE.

Imports System.Math
Imports OE
Imports OE.Core
Imports OE.Core.oeMath
Imports SlimDX

Namespace Core
    ''' <summary>
    ''' Responsible for Colors
    ''' </summary>
    ''' <remarks></remarks>
    Public Class oeColor
        Implements IComparable(Of oeColor)
        Protected m_c(4) As Single

        Public Property c(ByVal n As Byte) As Single
            Get
                If n < 4 Then
                    Return m_c(n)
                Else
                    Throw New Exception("Arrayindex musst by smaller than 4.", New System.ArgumentOutOfRangeException)
                End If
            End Get
            Set(ByVal value As Single)
                If n < 4 Then
                    m_c(n) = value
                Else
                    Throw New Exception("Arrayindex musst by smaller than 4.", New System.ArgumentOutOfRangeException)
                End If
            End Set
        End Property

        Public Property a() As Single
            Get
                Return m_c(0)
            End Get
            Set(ByVal value As Single)
                m_c(0) = value
            End Set
        End Property
        Public Property r() As Single
            Get
                Return m_c(1)
            End Get
            Set(ByVal value As Single)
                m_c(1) = value
            End Set
        End Property
        Public Property g() As Single
            Get
                Return m_c(2)
            End Get
            Set(ByVal value As Single)
                m_c(2) = value
            End Set
        End Property
        Public Property b() As Single
            Get
                Return m_c(3)
            End Get
            Set(ByVal value As Single)
                m_c(3) = value
            End Set
        End Property

        Public Property alpha() As Byte
            Get
                Return ComponentToByte(m_c(0))
            End Get
            Set(ByVal value As Byte)
                m_c(0) = Convert.ToSingle(value / 255)
            End Set
        End Property
        Public Property red() As Byte
            Get
                Return ComponentToByte(m_c(1))
            End Get
            Set(ByVal value As Byte)
                m_c(1) = Convert.ToSingle(value / 255)
            End Set
        End Property
        Public Property green() As Byte
            Get
                Return ComponentToByte(m_c(2))
            End Get
            Set(ByVal value As Byte)
                m_c(2) = Convert.ToSingle(value / 255)
            End Set
        End Property
        Public Property blue() As Byte
            Get
                Return ComponentToByte(m_c(3))
            End Get
            Set(ByVal value As Byte)
                m_c(3) = Convert.ToSingle(value / 255)
            End Set
        End Property

        Public Property D3DColor() As Direct3D.ColorValue
            Get
                'Return CType(Me, Direct3D.ColorValue)
                Return New Direct3D.ColorValue(m_c(0), m_c(1), m_c(2), m_c(3))
            End Get
            Set(ByVal value As Direct3D.ColorValue)
                m_c(0) = value.Alpha
                m_c(1) = value.Red
                m_c(2) = value.Green
                m_c(3) = value.Blue
            End Set
        End Property

        Public Property DrwColor() As System.Drawing.Color
            Get
                Return Drawing.Color.FromArgb(ComponentToByte(m_c(0)), _
                                              ComponentToByte(m_c(1)), _
                                              ComponentToByte(m_c(2)), _
                                              ComponentToByte(m_c(3)))
            End Get
            Set(ByVal value As System.Drawing.Color)
                m_c(0) = Convert.ToSingle(value.A / 255)
                m_c(1) = Convert.ToSingle(value.R / 255)
                m_c(2) = Convert.ToSingle(value.G / 255)
                m_c(3) = Convert.ToSingle(value.B / 255)
            End Set
        End Property



        Public Sub New()
            m_c(0) = 1.0
            m_c(1) = 0
            m_c(2) = 0
            m_c(3) = 0
        End Sub

        Public Sub New(ByVal rgb As Single)
            m_c(0) = 1
            m_c(1) = rgb
            m_c(2) = rgb
            m_c(3) = rgb
        End Sub

        Public Sub New(ByVal red As Single, ByVal green As Single, ByVal blue As Single)
            m_c(0) = 1
            m_c(1) = red
            m_c(2) = green
            m_c(3) = blue
        End Sub

        Public Sub New(ByVal alpha As Single, ByVal red As Single, ByVal green As Single, ByVal blue As Single)
            m_c(0) = alpha
            m_c(1) = red
            m_c(2) = green
            m_c(3) = blue
        End Sub

        Public Sub New(ByVal rgb As Byte)
            m_c(0) = 1
            m_c(1) = Convert.ToSingle(rgb / 255)
            m_c(2) = Convert.ToSingle(rgb / 255)
            m_c(3) = Convert.ToSingle(rgb / 255)
        End Sub

        Public Sub New(ByVal red As Byte, ByVal green As Byte, ByVal blue As Byte)
            m_c(0) = 1
            m_c(1) = Convert.ToSingle(red / 255)
            m_c(2) = Convert.ToSingle(green / 255)
            m_c(3) = Convert.ToSingle(blue / 255)
        End Sub

        Public Sub New(ByVal alpha As Byte, ByVal red As Byte, ByVal green As Byte, ByVal blue As Byte)
            m_c(0) = Convert.ToSingle(alpha / 255)
            m_c(1) = Convert.ToSingle(red / 255)
            m_c(2) = Convert.ToSingle(green / 255)
            m_c(3) = Convert.ToSingle(blue / 255)
        End Sub

        Public Sub New(ByVal Color As Drawing.Color)
            'D3DColor = Direct3D.ColorValue.FromColor(Color)
            m_c(0) = Color.A
            m_c(1) = Color.R
            m_c(2) = Color.G
            m_c(3) = Color.B
        End Sub

        Public Sub New(ByVal DxColor As Direct3D.ColorValue)
            D3DColor = DxColor
        End Sub

        Public Sub New(ByVal c() As Single)
            If c.Length = 4 Then
                m_c = c
            Else
                Throw New Exception("Parameter c() must have 4 elements in one dimension.", New System.ArgumentException)
            End If
        End Sub

        Public Sub New(ByVal c() As Byte)
            If c.Length = 4 Then
                m_c(0) = Convert.ToSingle(c(0) / 255)
                m_c(1) = Convert.ToSingle(c(1) / 255)
                m_c(2) = Convert.ToSingle(c(2) / 255)
                m_c(3) = Convert.ToSingle(c(3) / 255)
            Else
                Throw New Exception("Parameter c() must have 4 elements in one dimension.", New System.ArgumentException)
            End If
        End Sub

        Public Sub New(ByVal argb As Int32)
            DrwColor = Drawing.Color.FromArgb(argb)
        End Sub

        Public Sub New(ByVal oeCl As oeColor)
            c(0) = oeCl.c(0)
            c(1) = oeCl.c(1)
            c(2) = oeCl.c(2)
            c(3) = oeCl.c(3)
        End Sub



        Public Shared Narrowing Operator CType(ByVal obj As oeColor) As Drawing.Color
            Return Drawing.Color.FromArgb(obj.alpha, obj.red, obj.green, obj.blue)
        End Operator

        Public Shared Narrowing Operator CType(ByVal obj As oeColor) As Integer
            Return obj.D3DColor.ToArgb()
        End Operator

        Public Shared Narrowing Operator CType(ByVal obj As oeColor) As Direct3D.ColorValue
            Return New Direct3D.ColorValue(obj.a, obj.r, obj.g, obj.b)
        End Operator

        Public Shared Narrowing Operator CType(ByVal obj As Drawing.Color) As oeColor
            Return New oeColor(obj)
        End Operator

        Public Shared Narrowing Operator CType(ByVal obj As Integer) As oeColor
            Return New oeColor(obj)
        End Operator

        Public Shared Narrowing Operator CType(ByVal obj As Direct3D.ColorValue) As oeColor
            Return New oeColor(obj)
        End Operator


        ''' <summary>
        ''' Negates the Color
        ''' </summary>
        ''' <param name="a"></param>
        ''' <returns></returns>
        ''' <remarks></remarks>
        Public Shared Operator +(ByVal a As oeColor) As oeColor
            Return New oeColor(1 - a.a, _
                               1 - a.r, _
                               1 - a.g, _
                               1 - a.b)
        End Operator

        Public Shared Operator -(ByVal a As oeColor) As oeColor
            Return New oeColor(-a.a, _
                               -a.r, _
                               -a.g, _
                               -a.b)
        End Operator

        Public Shared Operator +(ByVal a As oeColor, ByVal b As oeColor) As oeColor
            Return New oeColor(a.a + b.a, _
                               a.r + b.r, _
                               a.g + b.g, _
                               a.b + b.b)
        End Operator

        Public Shared Operator -(ByVal a As oeColor, ByVal b As oeColor) As oeColor
            Return New oeColor(a.a - b.a, _
                               a.r - b.r, _
                               a.g - b.g, _
                               a.b - b.b)
        End Operator

        Public Shared Operator *(ByVal a As oeColor, ByVal b As oeColor) As oeColor
            Return New oeColor(a.a * b.a, _
                               a.r * b.r, _
                               a.g * b.g, _
                               a.b * b.b)
        End Operator

        Public Shared Operator *(ByVal a As oeColor, ByVal b As Single) As oeColor
            Return New oeColor(a.a * b, _
                               a.r * b, _
                               a.g * b, _
                               a.b * b)
        End Operator

        Public Shared Operator *(ByVal b As Single, ByVal a As oeColor) As oeColor
            Return New oeColor(a.a * b, _
                               a.r * b, _
                               a.g * b, _
                               a.b * b)
        End Operator

        Public Shared Operator /(ByVal a As oeColor, ByVal b As oeColor) As oeColor
            Return New oeColor(a.a / b.a, _
                               a.r / b.r, _
                               a.g / b.g, _
                               a.b / b.b)
        End Operator

        Public Shared Operator /(ByVal a As oeColor, ByVal b As Single) As oeColor
            Return New oeColor(a.a / b, _
                               a.r / b, _
                               a.g / b, _
                               a.b / b)
        End Operator

        ''' <summary>
        ''' calculates the brightness of the color if b=True. Otherwise the result is the inverted brightness.
        ''' </summary>
        ''' <param name="a"></param>
        ''' <param name="b"></param>
        ''' <returns></returns>
        ''' <remarks></remarks>
        Public Shared Operator &(ByVal a As oeColor, ByVal b As Boolean) As Single
            Return Convert.ToSingle(IIf(b, a.c(1) * 0.3 + a.c(2) * 0.6 + a.c(3) * 0.1, _
                                     1.0 - a.c(1) * 0.3 + a.c(2) * 0.6 + a.c(3) * 0.1))
        End Operator


        Public Shared Operator =(ByVal a As oeColor, ByVal b As oeColor) As Boolean
            Return (a.a = b.a And _
                    a.r = b.r And _
                    a.g = b.g And _
                    a.b = b.b)
        End Operator

        Public Shared Operator <>(ByVal a As oeColor, ByVal b As oeColor) As Boolean
            Return Not a = b
        End Operator

        Public Shared Operator <(ByVal c1 As oeColor, ByVal c2 As oeColor) As Boolean
            Return Convert.ToBoolean(IIf(c1 & True < c2 & True, c1, c2))
        End Operator

        Public Shared Operator <=(ByVal c1 As oeColor, ByVal c2 As oeColor) As Boolean
            Return Convert.ToBoolean(IIf(c1 & True <= c2 & True, c1, c2))
        End Operator

        Public Shared Operator >(ByVal c1 As oeColor, ByVal c2 As oeColor) As Boolean
            Return Convert.ToBoolean(IIf(c1 & True > c2 & True, c1, c2))
        End Operator

        Public Shared Operator >=(ByVal c1 As oeColor, ByVal c2 As oeColor) As Boolean
            Return Convert.ToBoolean(IIf(c1 & True >= c2 & True, c1, c2))
        End Operator

        Public Shared Operator Like(ByVal c1 As oeColor, ByVal c2 As oeColor) As Boolean
            Return Convert.ToBoolean(IIf((Round(c1.c(0), 5, MidpointRounding.AwayFromZero) = Round(c2.c(0), 5, MidpointRounding.AwayFromZero)) _
                                     And (Round(c1.c(1), 5, MidpointRounding.AwayFromZero) = Round(c2.c(1), 5, MidpointRounding.AwayFromZero)) _
                                     And (Round(c1.c(2), 5, MidpointRounding.AwayFromZero) = Round(c2.c(2), 5, MidpointRounding.AwayFromZero)) _
                                     And (Round(c1.c(3), 5, MidpointRounding.AwayFromZero) = Round(c2.c(3), 5, MidpointRounding.AwayFromZero)), _
                                     True, False))
        End Operator



        Public Sub Negate()
            c(0) = (+Me).c(0)
            c(1) = (+Me).c(1)
            c(2) = (+Me).c(2)
            c(3) = (+Me).c(3)
        End Sub

        Public Function Brightness() As Single
            Return Me & True
        End Function

        Public Function InterpolateWith(ByVal other As oeColor, ByVal p As Single) As oeColor
            Return Me + p * (other - Me)
        End Function

        Public Sub MakeRandom(Optional ByVal Alpha As Single = 1.0)
            Dim temp As oeColor = oeRandom.Color(Alpha)
            c(0) = temp.c(0)
            c(1) = temp.c(1)
            c(2) = temp.c(2)
            c(3) = temp.c(3)
        End Sub

        Public Sub ToLog(Optional ByVal AddInfo As String = "")
            oeLog.LogType(Me, AddInfo)
        End Sub

        Public Shared Function Min(ByVal c1 As oeColor, ByVal c2 As oeColor) As oeColor
            Return New oeColor(Convert.ToSingle(IIf(c1.c(0) < c2.c(0), c1.c(0), c2.c(0))), _
                               Convert.ToSingle(IIf(c1.c(1) < c2.c(1), c1.c(1), c2.c(1))), _
                               Convert.ToSingle(IIf(c1.c(2) < c2.c(2), c1.c(2), c2.c(2))), _
                               Convert.ToSingle(IIf(c1.c(3) < c2.c(3), c1.c(3), c2.c(3))))
        End Function

        Public Shared Function Max(ByVal c1 As oeColor, ByVal c2 As oeColor) As oeColor
            Return New oeColor(Convert.ToSingle(IIf(c1.c(0) > c2.c(0), c1.c(0), c2.c(0))), _
                               Convert.ToSingle(IIf(c1.c(1) > c2.c(1), c1.c(1), c2.c(1))), _
                               Convert.ToSingle(IIf(c1.c(2) > c2.c(2), c1.c(2), c2.c(2))), _
                               Convert.ToSingle(IIf(c1.c(3) > c2.c(3), c1.c(3), c2.c(3))))
        End Function


        Public Shared Function Brightness(ByVal c As oeColor) As Single
            Return c & True
        End Function

        Public Shared Function Interpolate(ByVal c1 As oeColor, ByVal c2 As oeColor, ByVal p As Single) As oeColor
            Return c1 + p * (c2 - c1)
        End Function



        Protected Function ComponentToByte(ByVal clcomponent As Single) As Byte
            Return Convert.ToByte(IIf(clcomponent > 1.0, 255, IIf(clcomponent < 0.0, 0, clcomponent * 255)))
        End Function

        Public Shared Sub oeColorToLog(ByVal a As oeColor, Optional ByVal AddInfo As String = "")
            oeLog.LogType(a, AddInfo)
        End Sub

        Public Function CompareTo(ByVal obj As oeColor) As Integer Implements IComparable(Of oeColor).CompareTo
            Return Convert.ToInt32(IIf(Me Like obj, 0, IIf(Me > obj, 1, -1)))
        End Function

    End Class

End Namespace